import requests
import re
import json
import execjs
import time
import random
import muggle_ocr
import urllib3

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)


class sn_login:
    def __init__(self, userdict, kw=''):
        self.kw = kw
        self.userdict = userdict
        self.username = ''
        self.password = ''
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36'
        }
        self.sess = requests.session()
        self.servertm = time.time()
        self.sdk = muggle_ocr.SDK(conf_path='./weibo_code/wb-CNNX-GRU-H64-CTC-C1_model.yaml')
        self.code = ''
        self.uid = ''
        self.nonce = ''
        self.pubkey = ''
        self.rsakv = ''
        self.su = ''
        self.urlist = []
        self.cookiesdict = {}

    def get_code(self):
        url = 'https://login.sina.com.cn/cgi/pin.php?'
        params = {
            'r': str(random.randint(0, 99999999)).zfill(8),
            's': '0',
        }
        pngs = self.sess.get(url=url, params=params, verify=False).content
        with open('code.png', 'wb') as f:
            f.write(pngs)
        code = self.sdk.predict(image_bytes=pngs)
        # print(code)
        self.code = code

    def prelogin(self):
        self.su = self.get_js_function('./微博login.js', 'account_encode', self.username, '', '')
        url = 'https://login.sina.com.cn/sso/prelogin.php?'
        self.headers['Host'] = 'login.sina.com.cn'
        self.headers['Referer'] = 'https://login.sina.com.cn/signup/signin.php'
        params = {
            'entry': 'account',
            'callback': 'sinaSSOController.preloginCallBack',
            'su': self.su,
            'rsakt': 'mod',
            'client': 'ssologin.js(v1.4.15)',
            '_': int(time.time()*1000),
        }
        resp = self.sess.get(url=url, headers=self.headers, params=params, verify=False)
        resp = json.loads(re.findall('sinaSSOController.preloginCallBack\((.*?)\)', resp.text)[0])
        self.servertm = resp.get('servertime')
        self.nonce = resp.get('nonce')
        self.pubkey = resp.get('pubkey')
        self.rsakv = resp.get('rsakv')

    # 调用JS文件生成加密参数
    def login(self):
        get_js = self.get_js_function('./微博login.js', 'jiemi', self.password, self.pubkey, self.nonce)
        sp = get_js
        data = {
            'entry': 'account',
            'gateway': '1',
            'from': 'null',
            'savestate': '30',
            'useticket': '0',
            'pagerefer': '',
            'vsnf': '1',
            'door': self.code,
            'su': self.su,
            'service': 'account',
            'servertime': self.servertm,
            'nonce': self.nonce,
            'pwencode': 'rsa2',
            'rsakv': self.rsakv,
            'sp': sp,
            'sr': '1536*864',
            'encoding': 'UTF-8',
            'cdult': '3',
            'domain': 'sina.com.cn',
            'prelt': '53',
            'returntype': 'TEXT',
        }
        resp = self.sess.post(
            url=f'https://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.15)&_={int(self.servertm * 1000)}',
            headers=self.headers, data=data, verify=False).json()
        self.uid = resp.get('uid')
        print(f'https://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.15)&_={int(self.servertm * 1000)}')
        # print('login: ', resp)
        if resp.get('retcode') == '0':
            print(f'account {self.username} login success')
        else:
            print(f'account {self.username} login fail!!!')

    def crossdom(self):
        self.headers['Host'] = 'passport.weibo.com'
        self.headers['Referer'] = 'https://login.sina.com.cn/'
        resp = self.sess.get(url=self.urlist[1], headers=self.headers, verify=False)
        # print('crossdom: ', resp.text)

    def passport_97973(self):
        self.headers['Host'] = 'passport.weibo.cn'
        self.headers['Referer'] = 'https://login.sina.com.cn/'
        resp = self.sess.get(url=self.urlist[2], headers=self.headers, verify=False)
        # print('passport: ', resp.text)

    def crossdom2(self):
        url = 'https://login.sina.com.cn/crossdomain2.php?action=login&entry=account&r=https%3A%2F%2Flogin.sina.com.cn%2F'
        self.headers['Host'] = 'login.sina.com.cn'
        self.headers['Referer'] = 'https://login.sina.com.cn/signup/signin.php'
        resp = self.sess.get(url=url, headers=self.headers, verify=False).text
        arrays = re.findall('sinaSSOController.setCrossDomainUrlList\((.*?)\)', resp)[0]
        self.urlist = self.get_js_function('./微博login.js', 'redirects', arrays, '', '')

    def get_ticket(self):
        self.headers['Host'] = 'passport.weibo.com'
        self.headers['Referer'] = 'https://login.sina.com.cn/'
        resp = self.sess.get(url=self.urlist[0], headers=self.headers, verify=False)
        # print('ticket: ', resp.text)

    def turn_to_weibo(self):
        self.headers['Host'] = 'weibo.com'
        self.headers['Referer'] = 'http://my.sina.com.cn/'
        resp = self.sess.get(url=f'https://weibo.com/u/{self.uid}/home?wvr=5', headers=self.headers, verify=False)
        if resp.status_code == requests.codes.ok:
            cookies = ''
            cookie_dict = requests.utils.dict_from_cookiejar(self.sess.cookies)
            for key, value in cookie_dict.items():
                cookie = key + '=' + value + ';'
                cookies += cookie
            # print(f"Get account {self.username}'s cookie: {cookies}")
            print(f"Get account {self.username}'s cookie success")
            self.cookiesdict.setdefault(self.username, cookies)
        else:
            print(f'status code: {resp.status_code}')

    @staticmethod
    def get_js_function(js_path, func_name, arg1, arg2, arg3):
        with open(js_path, encoding='utf-8') as fp:
            js = fp.read()
            ctx = execjs.compile(js)
            return ctx.call(func_name, arg1, arg2, arg3)

    def mains(self):
        for username, password in self.userdict.items():
            self.username = username
            self.password = password
            self.prelogin()
            self.get_code()
            try:
                self.login()
            except Exception as e:
                print(e)
            self.crossdom2()
            self.get_ticket()
            # self.crossdom()
            # self.passport_97973()
            self.turn_to_weibo()
        return self.cookiesdict


if __name__ == '__main__':
    userdict = {
        '17352910858': '**********',
        '13695540308': '**********'
    }
    cookies = sn_login(userdict).mains()
    print(cookies)